/*
 * Copyright (c) 2024-2025 LTC-CN. All rights reserved.
 * <p>
 * This file is part of the ltc-cn-springboot project.
 * <p>
 * ltc-cn-springboot is distributed under the terms of the MIT License.
 * For details, see the accompanying LICENSE file or visit:
 * <a href="https://www.ltc-cn.top/projects">...</a>
 */

package top.ltc_cn.springboot_tools.tools.passwordUtils;

import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Base64;

@Slf4j
@Component
public class EncryptUtils {

    private EncryptUtils() {} // 防止实例化

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    private static final String SECRET = "AES";
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";

    /**
     * AES加密ECB模式PKCS7Padding填充方式
     * @param str 字符串
     * @param key 密钥
     * @return 加密字符串
     * @throws Exception 异常信息
     */
    public static String aes256ECBPkcs7PaddingEncrypt(String str, String key) throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); // 创建加密对象
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8); // 创建一个字节数组，用于保存密钥
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, SECRET)); // 初始化加密对象
        byte[] doFinal = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)); // 执行加密操作
        return new String(Base64.getEncoder().encode(doFinal)); // 返回加密后的字符串
    }

    /**
     * 加密
     *
     * @param plaintext 明文
     * @param key 密钥
     * @param iv IV (初始化向量)
     * @return 加密后的密文
     */
    public static String encrypt(String plaintext, byte[] key, byte[] iv) {
        try {
//            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
//            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
//            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
//
//            byte[] paddedPlaintext = plaintext.getBytes(StandardCharsets.UTF_8);
//            byte[] ciphertext = cipher.doFinal(paddedPlaintext);
//
//            byte[] combined = new byte[iv.length + ciphertext.length];
//            System.arraycopy(iv, 0, combined, 0, iv.length);
//            System.arraycopy(ciphertext, 0, combined, iv.length, ciphertext.length);
//
//            return Base64.getEncoder().encodeToString(combined);
            // 验证密钥长度是否为32字节
            if (key.length != 32) {
                throw new IllegalArgumentException("Key length must be 32 bytes for AES-256");
            }

//            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
//            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
//
//            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
//            byte[] encryptedData = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));

            // AES/CBC/PKCS7Padding模式
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");
            // AES
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, SECRET);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] encryptedData = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));

            // 将IV与加密数据合并
            byte[] result = new byte[iv.length + encryptedData.length];
            System.arraycopy(iv, 0, result, 0, iv.length);
            System.arraycopy(encryptedData, 0, result, iv.length, encryptedData.length);

            return Base64.getEncoder().encodeToString(result);
        } catch (Exception e) {
            log.error("[EncryptUtils] Encryption failed", e);
            throw new RuntimeException("[EncryptUtils] Encryption failed", e);
        }
    }

    /**
     * 解密
     *
     * @param encryptedText Base64编码的加密后的字符串（包含IV）
     * @param key           密钥
     * @return 解密后的明文
     */
    public static String decrypt(String encryptedText, byte[] key) {
        try {
            // 将Base64编码的字符串解码为字节数组
            byte[] combined = Base64.getDecoder().decode(encryptedText);

            // 分离IV和密文
            int ivLength = 16; // AES块大小通常为16字节
            byte[] iv = new byte[ivLength];
            byte[] ciphertext = new byte[combined.length - ivLength];
            System.arraycopy(combined, 0, iv, 0, ivLength);
            System.arraycopy(combined, ivLength, ciphertext, 0, ciphertext.length);

            // 创建Cipher实例并初始化为解密模式
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

            // 执行解密操作
            byte[] decryptedBytes = cipher.doFinal(ciphertext);
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("[EncryptUtils] Decryption failed", e);
        }
    }

    /**
     * 验证密钥长度是否符合AES要求
     *
     * @param key 密钥
     * @return 如果密钥有效则返回true，否则false
     */
    public static boolean validateKey(byte[] key) {
        // AES支持的密钥长度：128位（16字节）、192位（24字节）或256位（32字节）
        int keyLength = key.length;
        return keyLength == 16 || keyLength == 24 || keyLength == 32;
    }

}
